#ifndef _FUNCTIONDEFINITION_
#define _FUNCTIONDEFINITION_

#include "TreeNode.h"
#include "Variable.h"
#include "Statement.h"
#include "ReturnStatement.h"
#include "../BuiltInFunctionType.h"
#include <string>
#include <vector>

using namespace std;

class FunctionDefinition: public TreeNode
{
public:
    FunctionDefinition(string iFunctionName, vector<Variable*> iInputVariables, TreeNode* iBody, bool iIsBuiltIn = false);
    virtual ~FunctionDefinition();
    virtual void Accept(GeneralVisitor* iVisitor);

    void ResolveVariables();
    void ResolveFunctionCalls(set<FunctionDefinition*>& iAllFunctions);
    void ResolveClassConstructions(set<ClassDefinition*>& iAllClasses);
    void CheckExpressionTypes();

    string GetName()                { return fFunctionName; }
    unsigned int GetParamCount()    { return fInputVariables.size(); }
    unsigned int GetLocalsCount()   { return fLocalVars.size() - fInputVariables.size(); }

    // Vrati ukazatel na ReturnStatement obsazeny v fBody, nebo 0, pokud tam zadny takovy neni.
    ReturnStatement* GetReturnStatement();

    TreeNode* GetBody() { return fBody; }

    vector<Variable*> GetInputVars()                        { return fInputVariables; }

    vector<string> GetInputVarNames();
    vector<string> GetLocalVarNames();

    bool IsBuiltIn()                                        { return fIsBuiltIn; }
    void SetBuiltInFunctionType(BuiltInFunctionType iType)  { fBuiltInFunctionType = iType; }
    void SetBytecodeOffset(unsigned int iBytecodeOffset)    { fBytecodeOffset = iBytecodeOffset; }
    unsigned int GetBytecodeOffset()                        { return fBytecodeOffset; }
    void CheckBuiltInFunctionCallParams(map<string, ExpressionType*>& iVarTypes, vector<TreeNode*>& iCallParams);
    ExpressionType* GetBuiltInFunctionReturnType();

private:
    string fFunctionName;
    vector<Variable*> fInputVariables;
    TreeNode* fBody;
    set<string> fLocalVars;
    bool fIsBuiltIn;
    BuiltInFunctionType fBuiltInFunctionType;
    unsigned int fBytecodeOffset;
};

#endif
